-----------------------------------------------------------------------------------------------
-- Model Name 	: PIP
-- File Name	:	registers.vhd
-- Generated	:	23.07.2014
-- Author		:	Maya Oren and Chen Feigin
-- Project		:	FPGA project
------------------------------------------------------------------------------------------------
-- Description:  
------------------------------------------------------------------------------------------------
-- Revision:
--			Number 		Date	       	Name       			 	       Description
--			1.0		  05.08.2014  	Maya Oren and Chen Feigin	 		Creation

------------------------------------------------------------------------------------------------
--	Todo:
--							
------------------------------------------------------------------------------------------------

library ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity registers is
   generic (
     reset_activity_polarity_g  : std_logic :='1';      -- defines reset active polarity: '0' active low, '1' active high
     data_width_g               : natural := 8 ;        -- defines the width of the data lines of the system
	 addr_d_g					: natural := 1 ;		--Address Depth
	 info_size_g				: natural := 10 ;		-- defines the width of the output needed
--	 len_d_g					: natural := 2 ;
--     en_reg_address_g           : natural :=0;
     x1_reg_address_g           : natural :=0;
     y1_reg_address_g           : natural :=2;
     len1_reg_address_g         : natural :=4;
     width1_reg_address_g       : natural :=6;
	 x2_reg_address_g           : natural :=8;
     y2_reg_address_g           : natural :=10;
     len2_reg_address_g         : natural :=12;
     width2_reg_address_g       : natural :=14;
	 x1_reg_address2_g          : natural :=1;
     y1_reg_address2_g          : natural :=3;
     len1_reg_address2_g        : natural :=5;
     width1_reg_address2_g      : natural :=7;
	 x2_reg_address2_g          : natural :=9;
     y2_reg_address2_g          : natural :=11;
     len2_reg_address2_g        : natural :=13;
     width2_reg_address2_g      : natural :=15
           );
   port
   	   (
     sys_clk        : in std_logic; --system clock
     sys_reset      : in std_logic; --system reset
     -- wishbone slave interface
	 address_in        : in std_logic_vector ( addr_d_g -1 downto 0); -- address line
--	 len_in			   : in std_logic_vector ((data_width_g)*(len_d_g)-1 downto 0); -- len line
	 wr_en             : in std_logic; -- write enable: '1' for write, '0' for read
	 data_in           : in std_logic_vector (data_width_g-1 downto 0); -- data sent from WS
     valid_in          : in std_logic; -- validity of the address directed from WS
     data_out          : out std_logic_vector (data_width_g-1 downto 0); -- data sent to WS
     valid_data_out    : out std_logic; -- validity of data directed to WS
     -- PIP interface
 --    en_out            : out std_logic_vector (data_width_g-1 downto 0); -- enable data 
     x1_out        : out std_logic_vector (info_size_g-1 downto 0); -- 
     y1_out        : out std_logic_vector (info_size_g-1 downto 0); -- 
     len1_out       : out std_logic_vector (info_size_g-1 downto 0); -- 
     width1_out        : out std_logic_vector (info_size_g-1 downto 0);  -- 
	 x2_out        : out std_logic_vector (info_size_g-1 downto 0); --  
     y2_out        : out std_logic_vector (info_size_g-1 downto 0); -- 
     len2_out        : out std_logic_vector (info_size_g-1 downto 0); -- 
     width2_out        : out std_logic_vector (info_size_g-1 downto 0)  -- 
   	   );
end entity registers;

architecture arc_registers of registers is

--*****************************************************************************************************************************************************************--
---------- Constants	------------------------------------------------------------------------------------------------------------------------------------------------
--*****************************************************************************************************************************************************************--
--constant en_reg_address_c     : std_logic_vector(data_width_g * addr_d_g -1 downto 0) := conv_std_logic_vector(en_reg_address_g,  addr_d_g);
constant x1_reg_address_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector(x1_reg_address_g, addr_d_g);
constant y1_reg_address_c : std_logic_vector(addr_d_g -1 downto 0) := conv_std_logic_vector(y1_reg_address_g , addr_d_g);
constant len1_reg_address_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector(len1_reg_address_g, addr_d_g);
constant width1_reg_address_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector(width1_reg_address_g , addr_d_g);
constant x2_reg_address_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector(x2_reg_address_g, addr_d_g);
constant y2_reg_address_c : std_logic_vector(addr_d_g -1 downto 0) := conv_std_logic_vector(y2_reg_address_g, addr_d_g);
constant len2_reg_address_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector(len2_reg_address_g , addr_d_g);
constant width2_reg_address_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector( width2_reg_address_g, addr_d_g);
constant x1_reg_address2_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector(x1_reg_address2_g, addr_d_g);
constant y1_reg_address2_c : std_logic_vector(addr_d_g -1 downto 0) := conv_std_logic_vector(y1_reg_address2_g , addr_d_g);
constant len1_reg_address2_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector(len1_reg_address2_g, addr_d_g);
constant width1_reg_address2_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector(width1_reg_address2_g , addr_d_g);
constant x2_reg_address2_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector(x2_reg_address2_g, addr_d_g);
constant y2_reg_address2_c : std_logic_vector(addr_d_g -1 downto 0) := conv_std_logic_vector(y2_reg_address2_g, addr_d_g);
constant len2_reg_address2_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector(len2_reg_address2_g , addr_d_g);
constant width2_reg_address2_c : std_logic_vector( addr_d_g -1 downto 0) := conv_std_logic_vector( width2_reg_address2_g, addr_d_g);
--*****************************************************************************************************************************************************************--
---------- 	Types	------------------------------------------------------------------------------------------------------------------------------------------------
--*****************************************************************************************************************************************************************--

--*****************************************************************************************************************************************************************--
---------- SIGNALS	------------------------------------------------------------------------------------------------------------------------------------------------
--*****************************************************************************************************************************************************************--
-- registers
-- first stage data in
signal x1_reg       : std_logic_vector (data_width_g-1 downto 0); 
signal y1_reg       : std_logic_vector (data_width_g-1 downto 0); 
signal len1_reg        : std_logic_vector (data_width_g-1 downto 0); 
signal width1_reg        : std_logic_vector (data_width_g-1 downto 0); 
signal x2_reg       : std_logic_vector (data_width_g-1 downto 0);  
signal y2_reg       : std_logic_vector (data_width_g-1 downto 0); 
signal len2_reg        : std_logic_vector (data_width_g-1 downto 0);  
signal width2_reg        : std_logic_vector (data_width_g-1 downto 0);
signal x12_reg       : std_logic_vector (data_width_g-1 downto 0); 
signal y12_reg       : std_logic_vector (data_width_g-1 downto 0); 
signal len12_reg        : std_logic_vector (data_width_g-1 downto 0); 
signal width12_reg        : std_logic_vector (data_width_g-1 downto 0); 
signal x22_reg       : std_logic_vector (data_width_g-1 downto 0);  
signal y22_reg       : std_logic_vector (data_width_g-1 downto 0); 
signal len22_reg        : std_logic_vector (data_width_g-1 downto 0);  
signal width22_reg        : std_logic_vector (data_width_g-1 downto 0);    


signal x1_reg_fin       : std_logic_vector (info_size_g-1 downto 0); -- x value left corner small pic1
signal y1_reg_fin       : std_logic_vector (info_size_g-1 downto 0); -- y value left corner small pic1
signal len1_reg_fin        : std_logic_vector (info_size_g-1 downto 0); -- len value small pic1
signal width1_reg_fin        : std_logic_vector (info_size_g-1 downto 0); -- width value small pic1
signal x2_reg_fin       : std_logic_vector (info_size_g-1 downto 0); -- x value left corner small pic2
signal y2_reg_fin       : std_logic_vector (info_size_g-1 downto 0); -- y value left corner small pic2
signal len2_reg_fin        : std_logic_vector (info_size_g-1 downto 0); -- len value small pic2
signal width2_reg_fin        : std_logic_vector (info_size_g-1 downto 0); -- width value small pic2

begin

--*****************************************************************************************************************************************************************--
---------- Processes	------------------------------------------------------------------------------------------------------------------------------------------------
--*****************************************************************************************************************************************************************--
regs_outputs_proc:
x1_out  <= x1_reg_fin ;
y1_out <= y1_reg_fin ;
len1_out  <= len1_reg_fin ;
width1_out  <= width1_reg_fin;
x2_out  <= x2_reg_fin ;
y2_out  <= y2_reg_fin;
len2_out <= len2_reg_fin ;
width2_out <= width2_reg_fin;

---------------------------------------------------- registers process ----------------------------------------------------------------------------------
x1_reg_proc:
process(sys_clk,sys_reset)
	begin
 		if sys_reset = reset_activity_polarity_g then
 		  		 x1_reg_fin <= (others => '0');
 		elsif rising_edge(sys_clk) then
 		   if ( (valid_in = '1') and (wr_en = '1') and (address_in = x1_reg_address_c) ) then
					x1_reg <= data_in;
		   elsif ( (valid_in = '1') and (wr_en = '1') and (address_in = x1_reg_address2_c) ) then
					x12_reg <= data_in;
		   elsif (wr_en = '0') then
				x1_reg_fin <= x12_reg(1 downto 0) & x1_reg;
 		   else
 		     x1_reg_fin <= x1_reg_fin;
       end if; 			
    end if;
end process x1_reg_proc;


x2_reg_proc:
process(sys_clk,sys_reset)
	begin
 		if sys_reset = reset_activity_polarity_g then
 		  		 x2_reg_fin <= (others => '0');
 		elsif rising_edge(sys_clk) then
 		   if ( (valid_in = '1') and (wr_en = '1') and (address_in = x2_reg_address_c) ) then
				x2_reg <= data_in;
		   elsif ( (valid_in = '1') and (wr_en = '1') and (address_in = x2_reg_address2_c) ) then
					x22_reg <= data_in;
		   elsif (wr_en = '0') then
				x2_reg_fin <= x22_reg(1 downto 0) & x2_reg;
 		   else
 		     x2_reg_fin <= x2_reg_fin;
       end if; 			
    end if;
end process x2_reg_proc;

y1_reg_proc:
process(sys_clk,sys_reset)
	begin
 		if sys_reset = reset_activity_polarity_g then
 		  		 y1_reg_fin <= (others => '0');
 		elsif rising_edge(sys_clk) then
 		   if ( (valid_in = '1') and (wr_en = '1') and (address_in = y1_reg_address_c) ) then
				y1_reg <= data_in;
		   elsif ( (valid_in = '1') and (wr_en = '1') and (address_in = y1_reg_address2_c) ) then
					y12_reg <= data_in;
		   elsif (wr_en = '0') then
				y1_reg_fin <= y12_reg(1 downto 0) & y1_reg;
 		   else
 		     y1_reg_fin <= y1_reg_fin;
       end if; 			
    end if;
end process y1_reg_proc;

y2_reg_proc:
process(sys_clk,sys_reset)
	begin
 		if sys_reset = reset_activity_polarity_g then
 		  		 y2_reg_fin <= (others => '0');
 		elsif rising_edge(sys_clk) then
 		   if ( (valid_in = '1') and (wr_en = '1') and (address_in = y2_reg_address_c) ) then
				y2_reg <= data_in;
		   elsif ( (valid_in = '1') and (wr_en = '1') and (address_in = y2_reg_address2_c) ) then
					y22_reg <= data_in;
		   elsif (wr_en = '0') then
				y2_reg_fin <= y22_reg(1 downto 0) & y2_reg;
 		   else
 		     y2_reg_fin <= y2_reg_fin;
       end if; 			
    end if;
end process y2_reg_proc;


len1_reg_proc:
process(sys_clk,sys_reset)
	begin
 		if sys_reset = reset_activity_polarity_g then
 		  		 len1_reg_fin <= (others => '0');
 		elsif rising_edge(sys_clk) then
 		   if ( (valid_in = '1') and (wr_en = '1') and (address_in = len1_reg_address_c) ) then
				len1_reg <= data_in;
		   elsif ( (valid_in = '1') and (wr_en = '1') and (address_in = len1_reg_address2_c) ) then
					len12_reg <= data_in;
		   elsif (wr_en = '0') then
				len1_reg_fin <= len12_reg(1 downto 0) & len1_reg;
 		   else
 		     len1_reg_fin <= len1_reg_fin;
       end if; 			
    end if;
end process len1_reg_proc;

len2_reg_proc:
process(sys_clk,sys_reset)
	begin
 		if sys_reset = reset_activity_polarity_g then
 		  		 len2_reg_fin <= (others => '0');
 		elsif rising_edge(sys_clk) then
 		   if ( (valid_in = '1') and (wr_en = '1') and (address_in = len2_reg_address_c) ) then
				len2_reg <= data_in;
		   elsif ( (valid_in = '1') and (wr_en = '1') and (address_in = len2_reg_address2_c) ) then
					len22_reg <= data_in;
		   elsif (wr_en = '0') then
				len2_reg_fin <= len22_reg(1 downto 0) & len2_reg;
 		   else
 		     len2_reg_fin <= len2_reg_fin;
       end if; 			
    end if;
end process len2_reg_proc;

width1_reg_proc:
process(sys_clk,sys_reset)
	begin
 		if sys_reset = reset_activity_polarity_g then
 		  		 width1_reg_fin <= (others => '0');
 		elsif rising_edge(sys_clk) then
 		   if ( (valid_in = '1') and (wr_en = '1') and (address_in = width1_reg_address_c) ) then
				width1_reg <= data_in;
		   elsif ( (valid_in = '1') and (wr_en = '1') and (address_in = width1_reg_address2_c) ) then
					width12_reg <= data_in;
		   elsif (wr_en = '0') then
				width1_reg_fin <= width12_reg(1 downto 0) & width1_reg;
 		   else
 		     width1_reg_fin <= width1_reg_fin;
       end if; 			
    end if;
end process width1_reg_proc;

width2_reg_proc:
process(sys_clk,sys_reset)
	begin
 		if sys_reset = reset_activity_polarity_g then
 		  		 width2_reg_fin <= (others => '0');
 		elsif rising_edge(sys_clk) then
 		   if ( (valid_in = '1') and (wr_en = '1') and (address_in = width2_reg_address_c) ) then
				width2_reg <= data_in;
		   elsif ( (valid_in = '1') and (wr_en = '1') and (address_in = width2_reg_address2_c) ) then
					width22_reg <= data_in;
		   elsif (wr_en = '0') then
				width2_reg_fin <= width22_reg(1 downto 0) & width2_reg;
 		   else
 		     width2_reg_fin <= width2_reg_fin;
       end if; 			
    end if;
end process width2_reg_proc;


---------------------------------------------------- read data process ----------------------------------------------------------------------------------

read_data_proc:
process(sys_clk,sys_reset)
	begin
 		if sys_reset = reset_activity_polarity_g then
 		  		 data_out <= (others => '0');
 		  		 valid_data_out <= '0';
 		elsif rising_edge(sys_clk) then
 		   if ( (valid_in = '1') and (wr_en = '0') ) then -- the wishbone slaves requests to read
 		     if (address_in = x1_reg_address_c)  then
 		       data_out <= x1_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = y1_reg_address_c) then
 		       data_out <= y1_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = len1_reg_address_c) then
 		       data_out <= len1_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = width1_reg_address_c) then
 		       data_out <= width1_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = x2_reg_address_c) then
 		       data_out <= x2_reg;
 		       valid_data_out <= '1';
			 elsif  (address_in = y2_reg_address_c) then
 		       data_out <= y2_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = len2_reg_address_c) then
 		       data_out <= len2_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = width2_reg_address_c) then
 		       data_out <= width2_reg;
 		       valid_data_out <= '1'; 
			 elsif (address_in = x1_reg_address2_c)  then
 		       data_out <= x12_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = y1_reg_address2_c) then
 		       data_out <= y12_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = len1_reg_address2_c) then
 		       data_out <= len12_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = width1_reg_address2_c) then
 		       data_out <= width12_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = x2_reg_address2_c) then
 		       data_out <= x22_reg;
 		       valid_data_out <= '1';
			 elsif  (address_in = y2_reg_address2_c) then
 		       data_out <= y22_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = len2_reg_address2_c) then
 		       data_out <= len22_reg;
 		       valid_data_out <= '1';
 		     elsif  (address_in = width2_reg_address2_c) then
 		       data_out <= width22_reg;
 		       valid_data_out <= '1'; 
 		     else
 		       data_out <= ( others => '0');
 		       valid_data_out <= '0';
 		     end if;
 		   else
 		     data_out <= ( others => '0');
 		     valid_data_out <= '0';
       end if; 			
    end if;
end process read_data_proc;

end architecture arc_registers;
